﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Linq;
using Styx;
using Styx.Helpers;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals.World;
using System.Windows.Forms;
using Styx.Common;
using Styx.Plugins;
using Styx.Pathing;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;




namespace MailboxManagerFree
{
    public class Item : INotifyPropertyChanged
    {
        private string _recipient;
        private bool _cod, _fullStacks;
        private string _object;
        private Money _price;
        private string _uiprice;

        //Cellformatting
        //Cellparsing

        public event PropertyChangedEventHandler PropertyChanged;

        public Item()
        {
            _recipient = "";
            _cod = false;
            _fullStacks = false;
            _object = "";
            _price = new Money(0);
            _uiprice = "";
        }

        public Item(string Recipient, bool CoD, string ObjectName, int PriceTotalCopper, bool FullStacksOnly)
        {
            _recipient = Recipient;
            _cod = CoD;
            _object = ObjectName;
            _price = new Money(PriceTotalCopper);
            _fullStacks = FullStacksOnly;
            _uiprice = _price.ToString();
        }

        public string Recipient
        {
            get { return _recipient; }
            set
            {
                _recipient = value;
                this.NotifyPropertyChanged("Recipient");
            }
        }

        public bool CoD
        {
            get { return _cod; }
            set
            {
                _cod = value;
                this.NotifyPropertyChanged("CoD");
            }
        }

        public string Object
        {
            get { return _object; }
            set
            {
                _object = value;
                this.NotifyPropertyChanged("Object");
            }
        }

        public Money Price
        {
            get { return new Money(this._price.TotalCopper); }
            set
            {
                _price = new Money(value.TotalCopper);
                this.NotifyPropertyChanged("Price");
            }
        }

        public string UIPrice
        {
            get { return _price.ToString(); }
            set
            {
                _price = value.ToMoney();
                _uiprice = value;
                this.NotifyPropertyChanged("UIPrice");
            }
        }

        public bool FullStacks
        {
            get { return _fullStacks; }
            set
            {
                _fullStacks = value;
                this.NotifyPropertyChanged("FullStacks");
            }
        }

        private void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public class MySettings : INotifyPropertyChanged
    {
        private bool _emptymailbox;
        private bool _runwhilefarming;
        private bool _pauseplugin;
        private bool _stackitems;
        private string _catchallrecipient;

        public event PropertyChangedEventHandler PropertyChanged;

        public MySettings()
        {
            _emptymailbox = false;
            _runwhilefarming = false;
            _pauseplugin = false;
            _stackitems = false;
            _catchallrecipient = null;
        }

        public MySettings(bool EmptyMailbox, bool RunWhileFarming, bool StackItems, string CatchAllRecipient)
        {
            _emptymailbox = EmptyMailbox;
            _runwhilefarming = RunWhileFarming;
            _pauseplugin = false;
            _stackitems = StackItems;
            _catchallrecipient = CatchAllRecipient;
        }

        public MySettings(MySettings s)
        {
            this._emptymailbox = s._emptymailbox;
            this._runwhilefarming = s._runwhilefarming;
            _pauseplugin = false;
            this._stackitems = s._stackitems;
            this._catchallrecipient = s._catchallrecipient;
        }

        public bool EmptyMailbox
        {
            get { return _emptymailbox; }
            set 
            { 
                _emptymailbox = value;
                this.NotifyPropertyChanged("EmptyMailbox");
            }
        }

        public bool RunWhileFarming
        {
            get { return _runwhilefarming; }
            set 
            { 
                _runwhilefarming = value;
                this.NotifyPropertyChanged("RunWhileFarming");
            }
        }

        public bool StackItems
        {
            get { return _stackitems; }
            set
            {
                _stackitems = value;
                this.NotifyPropertyChanged("StackItems");
            }
        }

        public string CatchAllRecipient
        {
            get { return _catchallrecipient; }
            set
            {
                _catchallrecipient = value;
                this.NotifyPropertyChanged("CatchAllRecipient");
            }
        }

        public bool PausePlugin
        {
            get { return _pauseplugin; }
            set
            {
                _pauseplugin = value;
                this.NotifyPropertyChanged("PausePlugin");
            }
        }

        private void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public class Recipient
    {
        //Declare variables for Recipients
        public string Name;
        public Dictionary<int,int> itemIDs;
        public Dictionary<string, int> itemNames;
        public List<string> itemTypes; //Applies to non-cod only

        public Recipient()
        {
            this.Name = "";
            itemIDs = new Dictionary<int, int>();
            itemNames = new Dictionary<string, int>();
            itemTypes = new List<string>();
        }

        //Constructor requires only Name and if mail will be sent as CoD
        public Recipient(String Name)
        {
            this.Name = Name;
            itemIDs = new Dictionary<int, int>();
            itemNames = new Dictionary<string, int>();
            itemTypes = new List<string>();
        }

        //Copy constructor
        public Recipient(Recipient OtherRecipient)
        {
            this.Name = OtherRecipient.Name;

            //Follows are checks if the lists contain any items, add if they do
            if (OtherRecipient.itemIDs.Count > 0)
            {
                foreach (var i in OtherRecipient.itemIDs)
                    this.itemIDs.Add(i.Key, i.Value);
            }

            if (OtherRecipient.itemNames.Count > 0)
            {
                foreach (var i in OtherRecipient.itemNames)
                    this.itemNames.Add(i.Key, i.Value);
            }

            if (OtherRecipient.itemTypes.Count > 0)
            {
                foreach (string i in OtherRecipient.itemTypes)
                    this.itemTypes.Add(i);
            }
        }

        public Dictionary<int, int> ItemIDs()
        {
            //Return new Dict to protect private data
            return new Dictionary<int, int>(this.itemIDs);
        }

        public Dictionary<string, int> ItemNames()
        {
            //Return new Dict to protect private data
            return new Dictionary<string, int>(this.itemNames);
        }

        public List<string> ItemTypes()
        {
            //Return new List to protect private data
            return new List<string>(this.itemTypes);
        }

        public void addItemByID(int ItemID, int PricePerOne)
        {
            bool exists = false;
            foreach (var i in this.itemIDs)
            {
                if (i.Key == ItemID)
                    exists = true;
            }
            //Check for if item already exists, add if not
            if(!exists)
                this.itemIDs.Add(ItemID, PricePerOne);
        }

        public void removeItemByID(int ItemID)
        {
            //Create temp list, cannot delete while processing Dictionary
            List<int> tempList = new List<int>();
            foreach (var i in this.itemIDs)
            {
                if (i.Key == ItemID)
                    tempList.Add(i.Key);
            }
            //Remove from Dictionary using temp list
            foreach (int x in tempList)
                this.itemIDs.Remove(x);
        }

        public void addItemByName(string ItemName, int PricePerOne)
        {
            bool exists = false;
            foreach (var i in this.itemNames)
            {
                if (i.Key == ItemName)
                    exists = true;
            }
            //Check for if item already exists, add if not
            if(!exists)
                this.itemNames.Add(ItemName, PricePerOne);
        }

        public void removeItemByName(string ItemName)
        {
            //Create temp list, cannot delete while processing Dictionary
            List<string> tempList = new List<string>();
            foreach (var i in this.itemNames)
            {
                if (i.Key == ItemName)
                    tempList.Add(i.Key);
            }
            //Remove from dictionary using temp list
            foreach (string x in tempList)
                this.itemNames.Remove(x);
        }

        public void addItemType(string ItemType)
        {
            //Check if already in list, add if not
            if(!this.itemTypes.Contains(ItemType))
                this.itemTypes.Add(ItemType);
        }

        public void removeItemType(string ItemType)
        {
            //Remove from internal list
            this.itemTypes.Remove(ItemType);
        }

        public void toLog()
        {
            string s = "";
            int u = this.Name.Count() - 2;
            for (int x = 0; x < u; x++)
                s += "*";
            Log("Recipient Name: " + (this.Name.ToCharArray().First().ToString() + (s) + this.Name.ToCharArray().Last().ToString()));
            string str = (this.Name.ToCharArray().First().ToString() +(this.Name.Count()) + this.Name.ToCharArray().Last().ToString());

            //If there are IDs, output them all
            if(itemIDs.Count > 0)
                Log("--Items By ID--");
            foreach (var i in itemIDs)
            {
                Log(string.Format("ID: " + i.Key + " || Price/1: " + i.Value));
            }

            //If there are Names, output them all
            if(itemNames.Count > 0)
                Log("--Items By Name--");
            foreach (var i in itemNames)
            {
                Log(string.Format("Name: " + i.Key + " || Price/1: " + i.Value));
            }

            //If there are Types, output them all
            if(itemTypes.Count > 0)
                Log("--Item Types--");
            foreach (var i in itemTypes)
            {
                Log("Type: " + i);
            }
        }

        public static XElement ToXml(Recipient rec)
        {
            return new XElement("Recipient",
                    new XElement("Name", rec.Name),
                    new XElement("ItemIDs",
                        from i in rec.itemIDs
                        select i.ToXml("ID")),
                    new XElement("ItemNames",
                        from i in rec.itemNames
                        select i.ToXml("Name")),
                    new XElement("ItemTypes",
                        from i in rec.itemTypes
                        select i.ToXml("Type"))
                    );
        }



        private void Log(string argument)
        {
            Logging.Write("[{0}] {1}", MailboxManager.name, argument);
        }
    }

    public class TradeItemType
    {
        private string type;
        private List<int> itemIDs;
        private List<string> itemNames;

        public TradeItemType(string Type)
        {
            this.type = Type;
            itemIDs = new List<int>();
            itemNames = new List<string>();
        }

        public string Type()
        {
            return type;
        }

        public List<int> ItemIDs()
        {
            return new List<int>(itemIDs);
        }

        public List<string> ItemNames()
        {
            return new List<string>(itemNames);
        }

        public void addItemByID(int ID)
        {
            itemIDs.Add(ID);
        }

        public void addItemByName(string Name)
        {
            itemNames.Add(Name);
        }
    }

    public class TradeItems
    {
        public Dictionary<string, int> Ores,Herbs,Skins,InksPigments,Elixers,Flasks,Potions,RareGems,CommonGems,RingsNecks,ChantMats,RareChants,CommonChants,LegArmors;

        public TradeItems()
        {
            //Mining & Blacksmithing
            // - MOP -
            Ores = new Dictionary<string, int>();
            Ores.Add("White Trillium Ore", 72103);
            Ores.Add("Trillium Bar", 72095);
            Ores.Add("Black Trillium Ore", 72094);
            Ores.Add("Living Steel", 72104);
            Ores.Add("Kyparite", 72093);
            Ores.Add("Heavy Ghost Iron Bar", 80432);
            Ores.Add("Folded Ghost Iron", 80431);
            Ores.Add("Ghost Iron Bar", 72096);
            Ores.Add("Blood Spirit", 80433);
            Ores.Add("Ghost Iron Ore", 72092);

            //Herbalism
            // - MOP -
            Herbs = new Dictionary<string, int>();
            Herbs.Add("Golden Lotus", 72238);
            Herbs.Add("Fool's Cap", 79011);
            Herbs.Add("Snow Lily", 79010);
            Herbs.Add("Silkweed", 72235);
            Herbs.Add("Green Tea Leaf", 72234);
            Herbs.Add("Rain Poppy", 72237);
            
            //Inscription
            // - MOP -
            InksPigments = new Dictionary<string, int>();
            InksPigments.Add("Starlight Ink", 79255);
            InksPigments.Add("Misty Pigment", 79253);
            InksPigments.Add("Ink of Dreams", 79254);
            InksPigments.Add("Scroll of Wisdom", 79731);
            InksPigments.Add("Shadow Pigment", 79251);

            //Alchemy - Elixers
            // - MOP -
            Elixers = new Dictionary<string, int>();
            Elixers.Add("Mantid Elixir", 76075);
            Elixers.Add("Mad Hozen Elixir", 76076);
            Elixers.Add("Elixir of Weaponry", 76077);
            Elixers.Add("Elixir of the Rapids", 76078);
            Elixers.Add("Elixir of Peace", 76079);
            Elixers.Add("Elixir of Perfection", 76080);
            Elixers.Add("Elixir of Mirrors", 76081);
            Elixers.Add("Monk's Elixir", 76083);

            //Alchemy - Flasks
            // - MOP -
            Flasks = new Dictionary<string, int>();
            Flasks.Add("Flask of Spring Blossoms", 76084);
            Flasks.Add("Flask of the Warm Sun", 76085);
            Flasks.Add("Flask of Falling Leaves", 76086);
            Flasks.Add("Flask of the Earth", 76087);
            Flasks.Add("Flask of Winter's Bite", 76088);

            //Alchemy - Potions
            // - MOP -
            Potions = new Dictionary<string, int>();
            Potions.Add("Virmen's Bite", 76089);
            Potions.Add("Potion of the Mountains", 76090);
            Potions.Add("Potion of Luck", 76091);
            Potions.Add("Potion of Focus", 76092);
            Potions.Add("Potion of the Jade Serpent", 76093);
            Potions.Add("Alchemist's Rejuvenation", 76094);
            Potions.Add("Potion of Mogu Power", 76095);
            Potions.Add("Darkwater Potion", 76096);
            Potions.Add("Master Mana Potion", 76098);
            Potions.Add("Master Healing Potion", 76097);
            
            //Jewelcrafting - Gems
            // - MOP -
            // - Blues
            RareGems = new Dictionary<string, int>();
            RareGems.Add("Primal Diamond", 76132);
            RareGems.Add("Imperial Amethyst", 76141);
            RareGems.Add("Serpent's Eye", 76734);
            RareGems.Add("Primordial Ruby", 76131);
            RareGems.Add("Vermilion Onyx", 76140);
            RareGems.Add("Wild Jade", 76139);
            RareGems.Add("Sun's Radiance", 76142);
            RareGems.Add("River's Heart", 76138);
            // - Greens
            CommonGems = new Dictionary<string, int>();
            CommonGems.Add("Tiger Opal", 76130);
            CommonGems.Add("Alexandrite", 76137);
            CommonGems.Add("Pandarian Garnet", 76136);
            CommonGems.Add("Sunstone", 76134);
            CommonGems.Add("Roguestone", 76135);
            CommonGems.Add("Lapis Lazuli", 76133);

            //Jewelcrafting - Crafted
            // - MOP -
            RingsNecks = new Dictionary<string, int>();
            RingsNecks.Add("Shadowfire Necklace", 83794);
            RingsNecks.Add("Band of Blood", 83801);
            RingsNecks.Add("Golembreaker Amulet", 83803);
            RingsNecks.Add("Heart of the Earth", 83796);
            RingsNecks.Add("Ornate Band", 83793);
            RingsNecks.Add("Lionsfall Ring", 83800);
            RingsNecks.Add("Lord's Signet", 83799);
            RingsNecks.Add("Reflection of the Sea", 83802);
            RingsNecks.Add("Roguestone Shadowband", 83798);
            RingsNecks.Add("Scrying Roguestone", 83795);
            RingsNecks.Add("Skymage Circle", 83805);
            RingsNecks.Add("Tiger Opal Pendant", 83806);
            RingsNecks.Add("Widow Chain", 83804);

            //Enchanting
            // - MOP -
            // - Mats
            ChantMats = new Dictionary<string, int>();
            ChantMats.Add("Ethereal Shard", 74247);
            ChantMats.Add("Greater Mysterious Essence", 74251);
            ChantMats.Add("Sha Crystal", 74248);
            ChantMats.Add("Spirit Dust", 74249);
            // - Chants
            // Rare -
            RareChants = new Dictionary<string, int>();
            RareChants.Add("Enchant Weapon - Colossus", 74727);
            RareChants.Add("Enchant Weapon - River's Song", 74728);
            RareChants.Add("Enchant Weapon - Windsong", 74723);
            RareChants.Add("Enchant Weapon - Jade Spirit", 74724);
            RareChants.Add("Enchant Weapon - Elemental Force", 74725);
            RareChants.Add("Enchant Weapon - Dancing Steel", 74726);
            // Common -
            CommonChants = new Dictionary<string, int>();
            CommonChants.Add("Enchant Off-Hand - Major Intellect", 74729);
            CommonChants.Add("Enchant Gloves - Superior Mastery", 74722);
            CommonChants.Add("Enchant Gloves - Super Strength", 74721);
            CommonChants.Add("Enchant Gloves - Superior Expertise", 74720);
            CommonChants.Add("Enchant Gloves - Greater Haste", 74719);
            CommonChants.Add("Enchant Boots - Pandaren's Step", 74718);
            CommonChants.Add("Enchant Boots - Blurred Speed", 74717);
            CommonChants.Add("Enchant Boots - Greater Precision", 74716);
            CommonChants.Add("Enchant Boots - Greater Haste", 74715);
            CommonChants.Add("Enchant Cloak - Superior Critical Strike", 74713);
            CommonChants.Add("Enchant Cloak - Superior Intellect", 74712);
            CommonChants.Add("Enchant Cloak - Greater Protection", 74711);
            CommonChants.Add("Enchant Cloak - Accuracy", 74710);
            CommonChants.Add("Enchant Chest - Superior Stamina", 74709);
            CommonChants.Add("Enchant Chest - Glorious Stats", 74708);
            CommonChants.Add("Enchant Chest - Mighty Spirit", 74707);
            CommonChants.Add("Enchant Chest - Super Resilience", 74706);
            CommonChants.Add("Enchant Bracer - Greater Agility", 74705);
            CommonChants.Add("Enchant Bracer - Exceptional Strength", 74704);
            CommonChants.Add("Enchant Bracer - Super Intellect", 74703);
            CommonChants.Add("Enchant Bracer - Major Dodge", 74701);
            CommonChants.Add("Enchant Bracer - Mastery", 74700);

            //Leatherworking
            // - MOP -
            LegArmors = new Dictionary<string, int>();
            LegArmors.Add("Brutal Leg Armor", 85568);
            LegArmors.Add("Sha-Touched Leg Armor", 85569);
            LegArmors.Add("Toughened Leg Armor", 85570);
            LegArmors.Add("Sha Armor Kit", 85559);
            LegArmors.Add("Angerhide Leg Armor", 83765);
            LegArmors.Add("Ironscale Leg Armor", 83763);
            LegArmors.Add("Shadowleather Leg Armor", 83764);

            //Skinning
            // - MOP -
            Skins = new Dictionary<string, int>();
            Skins.Add("Magnificent Hide", 72163);
            Skins.Add("Heavy Exotic Leather", 80221);
            Skins.Add("Sha-Touched Leather", 72162);
            Skins.Add("Exotic Leather", 72120);

            /*
            List.Add("", );
            List.Add("", );
            List.Add("", );
            List.Add("", );
            List.Add("", );
            List.Add("", );
            List.Add("", );
             * */
        }
    }

    partial class MailboxManager : HBPlugin
    {

        public override string Name { get { return "MailMan(Free)"; } }
        public static string name { get { return "MailMan(Free)"; } }
        
        public override string Author { get { return "No1KnowsY"; } }
        public override Version Version { get { return new Version(1, 0, 1); } }
        public LocalPlayer Me { get { return Styx.StyxWoW.Me; } }
        public static bool UseCoD = false;
        public static bool EmptyMailbox = false;
        public static bool RanOnce = false;
        public bool IsDone = true;
        public static BindingList<Item> items = new BindingList<Item>();
        public static TradeItems tradeItems = new TradeItems();
        public int NumberOfItemsRan = 0, NumberOfMailsSent = 0;
        public static MySettings myset = new MySettings();
        public string HBDefaultMailRecient
        {
            get
            {
                
                return Styx.Helpers.CharacterSettings.Instance.MailRecipient;
            }
        }
        public const string LuaDoSend =
                        "local id = \"{0}\" " +
                        "local stackPrice = {1} " +
                        "local recipent = '{2}' " +
                        "local fullSize = {3} " +
                        "local _,_,_,_,_,_,_,stackSize=GetItemInfo(id) " +
                        "local j=0 " +
                        "local i=0 " +
                        "for b=0,4 do " +
                          "for s=1,GetContainerNumSlots(b) do " +
                            "local n=GetContainerItemLink(b,s) " +
                                "if n then " +
                                  "if strfind(n,id) and i<12 then " +
                                    "_,c=GetContainerItemInfo(b,s) " +
                                        "if fullSize then " +
                                          "if c==stackSize then " +
                                            "j=j+c UseContainerItem(b,s) i=i+1 " +
                                          "end " +
                                        "else " +
                                          "j=j+c UseContainerItem(b,s) " +
                                          "i=i+1 " +
                                        "end " +
                                  "end " +
                                "end " +
                          "end " +
                        "end " +
                        "local codprice=j*(stackPrice/stackSize) " +
                        "local header,_=GetSendMailItem(1) " +
                        "SetSendMailCOD(codprice) " +
                        "SendMail(recipent,header,'')";

        public override bool WantButton { get { return true; } }

        private Form _configForm;
        public override void OnButtonPress()
        {
            if (_configForm == null || _configForm.IsDisposed || _configForm.Disposing)
                _configForm = new UI();
            
            _configForm.Show();
        }

        public void Log(string argument)
        {
            Logging.Write("[{0}] {1}", Name, argument);
        }

        public override void Initialize()
        {
            Dictionary<string, Dictionary<string, int>> TradeItemTypes = new Dictionary<string,Dictionary<string,int>>();
            MailboxManager.LoadSettings();
            tradeItems = new TradeItems();
            IsDone = true;
            
            Log("Loaded v" + Version);
        }

        public override void Dispose()
        {
        }

        Random rnd = new Random();
        public int ranNum(int min, int max)
        {
            return rnd.Next(min, max + 1);
        }

        public void SendMailLuaCommand(Item item)
        {
            Log("Sending '" + item.Object + "' to '" + item.Recipient.ToHiddenName() + "'."); 
            StyxWoW.SleepForLagDuration();
            var command = string.Format(LuaDoSend, item.Object, item.Price.TotalCopper, item.Recipient, item.FullStacks.ToString().ToLowerInvariant());
            Lua.DoString(command);
            NumberOfMailsSent++;
            //Log("Total letters sent this mailbox stop: " + NumberOfMailsSent + ".");
        }
        public void SendMailLuaCommandHBDefault(Item item)
        {
            if (!string.IsNullOrEmpty(HBDefaultMailRecient))
            {
                Log("Sending '" + item.Object + "' to '" + HBDefaultMailRecient.ToHiddenName() + "' since the item is listed as being sent to the toon you are logged in on.");
                StyxWoW.SleepForLagDuration();
                var command = string.Format(LuaDoSend, item.Object, 0, HBDefaultMailRecient, item.FullStacks.ToString().ToLowerInvariant());
                Lua.DoString(command);
                NumberOfMailsSent++;
            }
            else
            {
                Log("No HB default mail recipient set.  Please set one so these extra items can be mailed off.");
                Log("As such... Pausing Plugin!!");
                myset.PausePlugin = true;
            }
            //Log("Total letters sent this mailbox stop: " + NumberOfMailsSent + ".");
        }

        public override void Pulse()
        {
            if (myset.PausePlugin)
                return;

            if (IsDone)
            {
                if (!Styx.CommonBot.Frames.MailFrame.Instance.IsVisible)
                {
                    List<WoWGameObject> MailboxList = ObjectManager.GetObjectsOfType<WoWGameObject>()
                            .Where(o => o.SubType == WoWGameObjectType.Mailbox).ToList();
                    WoWGameObject mailbox = MailboxList.First();
                    while (Me.Location.Distance(mailbox.Location) > mailbox.InteractRange)
                        Navigator.MoveTo(mailbox.Location);
                    mailbox.Interact();
                    Thread.Sleep(1000);
                }
                Lua.DoString("MailFrameTab2:Click()");
                var sortedList =
                    (from d in items
                    orderby !d.CoD, d.Recipient, d.Object
                    select d).ToList();

                items = new BindingList<Item>(sortedList);
                IsDone = false;
            }
            else
            {
                uint count = 0;
                ObjectManager.Update();

                try
                {
                    //Get a count of all items of a type throughout the whole inventory
                    count = (uint)StyxWoW.Me.BagItems.Sum(i => i != null && i.IsValid && i.Name == items[NumberOfItemsRan].Object ? i.StackCount : 0);
                }
                catch (Exception ex)
                {
                    Log("Exception! : " + ex);
                }


                if (!items[NumberOfItemsRan].Recipient.Equals(StyxWoW.Me.Name))
                {
                    //Didn't feel like copy-pasting all that much
                    switch (sendToReturnInt(items[NumberOfItemsRan], count))
                    {
                        case 0:
                            //Send mail as listed in user settings, all seems fine
                            SendMailLuaCommand(items[NumberOfItemsRan]);
                            break;
                        case 1:
                            //Reset count to skip item, there are no more full stacks to send
                            count = 0;
                            break;
                        default:
                            //Not sure why I have this
                            break;

                    }
                }
                else
                {
                    //Yep, this was a lot easier, just add a few letters
                    switch (sendToReturnInt(items[NumberOfItemsRan], count))
                    {
                        case 0:
                            //Send mail to HB Default Recipient because item is listed to be sent to this toon
                            SendMailLuaCommandHBDefault(items[NumberOfItemsRan]);
                            break;
                        case 1:
                            //Reset count to skip this item, either way there are no more full stacks to send
                            count = 0;
                            break;
                        default:
                            //Again, I just like having it
                            break;

                    }
                }
                Thread.Sleep(1000);

                //Log("Items checked this mailbox stop: " + (NumberOfItemsRan + 1).ToString() + ".");

                //count = uint.Parse(Lua.GetReturnValues(string.Format(GetItemCount, items[NumberOfItemsRan].Object))[0]);
                if (count <= 0)
                    NumberOfItemsRan++;
                if (NumberOfItemsRan >= items.Count)
                {
                    Log("Total Items checked to mail this time: " + (NumberOfItemsRan + 1).ToString() + ".");
                    Log("Total letters sent this time: " + (NumberOfMailsSent).ToString() + ".");
                    NumberOfItemsRan = 0;
                    NumberOfMailsSent = 0;
                    IsDone = true;
                    myset.PausePlugin = true;
                    Log("Done mailing.  Plugin paused!");
                }
            }
        }

        public int sendToReturnInt(Item item, uint count)
        {
            //Get all stacks, then check for non-full.  If all remaining are not full & only full stacks to be sent then skip to next item
            int numNonFullStacks = 0;
            var x = StyxWoW.Me.BagItems.Where(i => i != null && i.IsValid && i.Name == item.Object);
            var maxStack = Lua.GetReturnVal<int>(string.Format("return GetItemInfo(\"{0}\")", item.Object), 7);
            foreach (var i in x)
            {
                if (i.StackCount < maxStack)
                    numNonFullStacks++;
            }

            //If set to only send full stacks & either the count is less than the maxSize or all remaining stacks are under maxSize
            //Then send items to Honorbuddy default mailRecipient as the catchall
            if (item.FullStacks && (count < maxStack || numNonFullStacks >= x.Count()))
            {
                Log("No full stacks remain of " + item.Object + ".");
                //Return 1 to switch:case to signify skipping of the rest of these items
                return 1;
            }
            //Else if count > 0 send
            else if (count > 0)
            {
                //Return 0 to switch:case to signify to send normal
                return 0;
            }

            return 2;
        }
    }
}


